package com.fingard.dsp.bank.directbank.cib01;

import com.fingard.FGBiz;
import com.fingard.constant.Format;
import com.fingard.db.JDBCHelper;
import com.fingard.dsp.bank.directbank.DirectBase;
import com.fingard.dsp.bank.reqrespobj.elecbillquery.ReqB006BillStateQry;
import com.fingard.dsp.bank.reqrespobj.elecbillquery.RetAtsB006BillStateQry;
import com.fingard.dsp.bank.reqrespobj.elecbillquery.detail.RetAtsB006BillStateQryDetail;
import com.fingard.dsp.bank.reqrespobj.elecbilltrans.ReqB003BillRespSubmit;
import com.fingard.dsp.bank.reqrespobj.elecbilltrans.ReqB112BillCancSubmit;
import com.fingard.dsp.bank.reqrespobj.elecbilltrans.RetAtsB003BillRespSubmit;
import com.fingard.dsp.bank.reqrespobj.elecbilltrans.RetAtsB112BillCancSubmit;
import com.fingard.dsp.bank.reqrespobj.elecbilltrans.detail.RetAtsB003BillRespSubmitDetail;
import com.fingard.dsp.bank.reqrespobj.elecbilltrans.detail.RetAtsB112BillCancSubmitDetail;
import com.fingard.net.ITcpClient;
import com.fingard.net.TcpPortClient;
import com.fingard.net.TcpReceiver;
import com.fingard.net.WebRequest;
import com.fingard.text.StringHelper;
import com.fingard.util.FtpUtil;
import com.fingard.util.TransIDHelper;
import com.fingard.xml.XElement;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.Connection;
import java.text.DecimalFormat;
import java.util.*;

public class CIB01Base extends DirectBase implements ITcpClient {
    public static final String INSERTRECEIPT = "INSERT INTO REQSEQIDMAPPING(URID,BANKCODE,BUSITYPE,TRANSDATE,REQSEQID,BANKREQSEQID) values (?,?,?,?,?,?);";
    public static final String SELECTRECEIPT = "SELECT TRANSDATE,REQSEQID,BANKREQSEQID FROM REQSEQIDMAPPING WHERE REQSEQID=? and BANKCODE=?;";

    private static TransIDHelper idHelper = new TransIDHelper(1, 999);
    private static final String STR_FORMAT = "00000000";
    DecimalFormat decimalFormat = new DecimalFormat(STR_FORMAT);

    private static TransIDHelper idHelper2 = new TransIDHelper(1, 9999);

    protected String getINDX() {
        return idHelper2.getNextIDStr();
    }

    protected String getQryTransID() {
        Date tmpDateNow = new Date();
        return Format.DateTime14Format.format(tmpDateNow) + idHelper.getNextIDStr();
    }

    protected String getCharset() {
        return getBankConfig().getCharset("UTF-8");
    }

    protected String getCharset2() {
        return getBankConfig().getCharset("GBK", "receipt");
    }

    protected void writeCommonHeaderEn(XmlTextWriter xmlWriter, String headXml) throws Exception {
        Date tmpDateNow = new Date();

        xmlWriter.writeStartDocByDeclaration("<?xml#version=\"1.0\"#" + headXml + "?>"
                + "<?FOX#FOXHEADER=\"100\"#VERSION=\"100\"#SECURITY=\"NONE\"#LANG=\"CHS\"?>");
        xmlWriter.writeStartElement("FOX");
        xmlWriter.writeStartElement("SIGNONMSGSRQV1");
        xmlWriter.writeStartElement("SONRQ");
        xmlWriter.writeElementString("DTCLIENT", Format.DateTimeFormat.format(tmpDateNow).replaceAll("-", "/").replaceAll(" ", "#"));
        xmlWriter.writeElementString("CID", bankFront.org);
        xmlWriter.writeElementString("USERID", bankFront.loginName);//客户号
        xmlWriter.writeElementString("USERPASS", bankFront.loginPasswd);
        xmlWriter.writeElementString("GENUSERKEY", "Y");
        xmlWriter.writeElementString("APPID", "MYAPP");
        xmlWriter.writeElementString("APPVER", "1.0");
        xmlWriter.writeEndElement();
        xmlWriter.writeEndElement();
    }

    /**
     * 1944报文格式
     *
     * @param xmlWriter
     * @param headXml
     * @throws Exception
     */
    protected void writeCommonQryHeaderEn(XmlTextWriter xmlWriter, String headXml) throws Exception {
        Date tmpDateNow = new Date();
        xmlWriter.writeStartDocByDeclaration("<?xml#version=\"1.0\"#" + headXml + "?>");
        xmlWriter.writeStartElement("FOX");
        xmlWriter.writeStartElement("SIGNONMSGSRQV1");
        xmlWriter.writeStartElement("SONRQ");
        xmlWriter.writeElementString("DTCLIENT", Format.DateTimeFormat.format(tmpDateNow).replaceAll("-", "/").replaceAll(" ", "#"));
        xmlWriter.writeElementString("CID", bankFront.org);
        xmlWriter.writeElementString("USERID", bankFront.loginName);//客户号
        xmlWriter.writeElementString("USERPASS", bankFront.loginPasswd);
        xmlWriter.writeElementString("GENUSERKEY", "Y");
        xmlWriter.writeElementString("APPID", "MYAPP");
        xmlWriter.writeElementString("APPVER", "1.0");
        xmlWriter.writeEndElement();
        xmlWriter.writeEndElement();

    }

    /**
     * 1988,9188批量报文格式
     *
     * @param xmlWriter
     * @throws Exception
     */
    protected void writeCommonBatPayHeaderEn(XmlTextWriter xmlWriter) throws Exception {
        Date tmpDateNow = new Date();
        xmlWriter.writeStartElement("FOX");
        xmlWriter.writeStartElement("SIGNONMSGSRQV1");
        xmlWriter.writeStartElement("SONRQ");
        xmlWriter.writeElementString("DTCLIENT", Format.DateTimeFormat.format(tmpDateNow).replaceAll("-", "/").replaceAll(" ", "#"));
        xmlWriter.writeElementString("CID", bankFront.org);
        xmlWriter.writeElementString("USERID", bankFront.loginName);//客户号
        xmlWriter.writeElementString("USERPASS", bankFront.loginPasswd);
        xmlWriter.writeElementString("GENUSERKEY", "Y");
        xmlWriter.writeElementString("APPID", "MYAPP");
        xmlWriter.writeElementString("APPVER", "1.0");
        xmlWriter.writeEndElement();
        xmlWriter.writeEndElement();

    }

    /**
     * 票据池公共报文头
     *
     * @param xmlWriter
     * @throws Exception
     */
    protected void writeCommonBillPoolHeaderEn(XmlTextWriter xmlWriter) throws Exception {
//        xmlWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" standalone=\"yes\"?><?FOX FOXHEADER=\"100\" VERSION=\"100\" SECURITY=\"NONE\" LANG=\"CHS\"?>");
        Date tmpDateNow = new Date();
        xmlWriter.writeStartElement("FOX");
        xmlWriter.writeStartElement("SIGNONMSGSRQV1");
        xmlWriter.writeStartElement("SONRQ");
        xmlWriter.writeElementString("DTCLIENT", Format.DateTimeFormat.format(tmpDateNow));
        xmlWriter.writeElementString("CID", bankFront.org);
        xmlWriter.writeElementString("USERID", bankFront.loginName);//客户号
        xmlWriter.writeElementString("USERPASS", bankFront.loginPasswd);
        xmlWriter.writeElementString("GENUSERKEY", "N");
        xmlWriter.writeElementString("LANGUAGE", "ZH_CN");
        xmlWriter.writeElementString("APPID", "XYFIB");
        xmlWriter.writeElementString("APPVER", "1000");
        xmlWriter.writeEndElement();
        xmlWriter.writeEndElement();

    }

    protected void writeCommonHeader(XmlTextWriter xmlWriter) throws Exception {
        String headXml = "standalone=\"yes\"";
        writeCommonHeaderEn(xmlWriter, headXml);
    }

    /**
     * 9108单笔实时代收报文通用节点
     *
     * @param xmlWriter
     * @param header
     * @throws Exception
     */
    protected void writeCommonHeader(XmlTextWriter xmlWriter, CIB01Header header) throws Exception {
        xmlWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" encoding=\"" + getCharset() + "\"?>");
        xmlWriter.writeStartElement("Message");
        xmlWriter.writeStartElement("Head");
        xmlWriter.writeElementString("CorpNo", header.CorpNo);
        xmlWriter.writeElementString("Version", header.Version);
        xmlWriter.writeElementString("TranCode", header.TranCode);
        xmlWriter.writeElementString("FeeNo", header.FeeNo);
        xmlWriter.writeEndElement();
    }

    protected String writeContentLength(XmlTextWriter xmlWriter) throws Exception {
        String headXml = "POST <URL> HTTP/1.0\r\n";
        headXml += "USER-Agent: <Client Application Name>\r\n";
        headXml += "Content-Type: application/x-fox\r\n";
        headXml += "Content-Length: ";
        String bodyXml = xmlWriter.toXmlString().replace("      ", "").replaceAll("\n", "").replaceAll("\r", "")
                .replaceAll("\r\n", "").replaceAll("#", " ").replaceAll("/0", "/");
        int length = bodyXml.getBytes("gbk").length;
        String xmlSend = headXml + bodyXml;
        xmlSend = xmlSend.replaceAll("Content-Length: ", "Content-Length: " + length + "\r\n\r\n");
        return xmlSend;

    }

    protected String[] sendToBankReceipt(String p_reqStr, String transType, String commandCode) throws Exception {
        String[] retStr = new String[]{"", ""};
        if (StringHelper.hasAnyChar(transType) && StringHelper.hasAnyChar(commandCode)) {
            this.detailSimulateForBank(bankFront.bankCode, transType, commandCode, p_reqStr, retStr);
            if (retStr[1].length() > 0) {
                return retStr;
            }
        }
        return sendToBankReceipt(p_reqStr);
    }

    protected String[] sendToBankReceipt(String p_reqStr) throws Exception {
        String[] retStr = new String[]{"", ""};
        String charset = getCharset2();//GBK
        WriteBankLogLn("1.提交银行的地址：" + "http://" + bankFront.serverIP + ":" + bankFront.serverPort);
        int n = p_reqStr.getBytes(charset).length;
        String p_head = decimalFormat.format(n);
        String p_string = p_reqStr;
        WriteBankLogStep2(p_string);
        WebRequest tmpWebRequest = new WebRequest("http://" + bankFront.serverIP + ":" + bankFront.serverPort);
        tmpWebRequest.setConnectTimeout(60000);
        tmpWebRequest.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        tmpWebRequest.setRequestProperty("connection", "Close");
        String charsetName = charset;
        byte[] tmpToWriteBytes = p_string.getBytes(charsetName);
        retStr = tmpWebRequest.upload(tmpToWriteBytes, charsetName);
        WriteBankLogStep3(retStr[1]);
        return retStr;
    }

    protected String[] sendToBank(String p_reqStr) throws Exception {
        return sendToBank(p_reqStr, "", "");
    }

    protected String[] sendToBank(String p_reqStr, String transType, String commandCode) throws Exception {
        String[] retStr = new String[]{"", ""};

        if (StringHelper.hasAnyChar(transType) && StringHelper.hasAnyChar(commandCode)) {
            this.detailSimulateForBank(bankFront.bankCode, transType, commandCode, p_reqStr, retStr);
            if (retStr[1].length() > 0) {
                return retStr;
            }
        }

        WriteBankLogLn("2.提交银行的地址：" + bankFront.serverIP + ":" + bankFront.serverPort);
        //发送银行前置
        TcpPortClient tmpClient = new TcpPortClient(bankFront.serverIP, Integer.parseInt(bankFront.serverPort), this);
        String tmpCharset = "GBK";
        byte[] tmpBytesBody = p_reqStr.getBytes(tmpCharset);

        WriteBankLogStep2(p_reqStr);
        TcpReceiver tmpReceiver = tmpClient.sendMessage(tmpBytesBody);
        retStr[0] = tmpReceiver.connState;
        if (tmpReceiver.recBytes != null) {
            retStr[1] = new String(tmpReceiver.recBytes, 0, tmpReceiver.readedLength, tmpCharset);
            WriteBankLogStep3(retStr[1]);
        } else {
            retStr[1] = tmpReceiver.getConnMsg();
        }
        if (!tmpReceiver.isCompleted) {
            WriteBankLogLn(tmpReceiver.getConnMsg());
            throw new Exception(tmpReceiver.getConnMsg());
        }
        return retStr;
    }

    public void getContentLength(TcpReceiver p_receiver) throws Exception {
        if (p_receiver.contentLength == -1) {
            String tmpCharset = "GBK";
            String tmpRecNow = new String(p_receiver.recBytes, 0, p_receiver.readedLength, tmpCharset);
            if (tmpRecNow.indexOf("</FOX>") >= 0) {
                p_receiver.contentLength = p_receiver.readedLength;
                p_receiver.contentStartIndex = 0;
            }
        }
    }

    /**
     * 电子回单通用报文头
     *
     * @param xmlWriter
     * @param head
     * @throws Exception
     */
    protected void writeHeaderReceipt(XmlTextWriter xmlWriter, CIB01Header head) throws Exception {
        Date tmpDateNow = new Date();
        xmlWriter.writeStartElement("FOX");
        xmlWriter.writeStartElement("SIGNONMSGSRQV1");
        xmlWriter.writeStartElement("SONRQ");
        xmlWriter.writeElementString("DTCLIENT", Format.DateTimeFormat.format(tmpDateNow));
        xmlWriter.writeElementString("CID", bankFront.org);
        xmlWriter.writeElementString("USERID", bankFront.loginName);//客户号
        xmlWriter.writeElementString("USERPASS", bankFront.loginPasswd);
        xmlWriter.writeElementString("GENUSERKEY", "N");
        xmlWriter.writeElementString("APPID", "XYFIB");
        xmlWriter.writeElementString("APPVER", "1000");
        xmlWriter.writeEndElement();
        xmlWriter.writeEndElement();
    }

    //上送格式为json格式
    protected String[] sendToATS(String jsonData) throws Exception {
        String[] retStr = new String[]{"", ""};
        WriteBankLogLn("2.提交ATS的地址：" + FGBiz.dspCenter.dspSet.receiptPushServerUrl);

        //发送ATS
        WebRequest tmpRequest = new WebRequest(FGBiz.dspCenter.dspSet.receiptPushServerUrl);
        tmpRequest.setConnectTimeout(60000);
        tmpRequest.setRequestProperty("connection", "Close");
        tmpRequest.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        String charsetName = getCharset();
        WriteBankLogLn("3.推送给ATS的json数据" + jsonData);
        byte[] tmpWriteBytes = jsonData.getBytes(charsetName);
        retStr = tmpRequest.upload(tmpWriteBytes, charsetName);
        WriteBankLogLn("4.返回的数据" + retStr[1]);

        return retStr;
    }

    /**
     * 临时文件保存批次号或者文件名及id
     *
     * @param cltRefNo 批次号
     * @param fileName 文件名
     * @param fileId   文件id
     * @throws Exception
     */
    protected void generateReceiptCodeFile(String cltRefNo, String fileName, String fileId) throws Exception {
        String path = "";
        String filePath = "";
        String newFileContent = "";
        FileOutputStream fos = null;
        try {

            if ("".equals(cltRefNo) && !"".equals(fileName)) {
                path = FGBiz.dspCenter.dspSet.dataDirPath + File.separator + "dataFile" + File.separator + bankFront.code + File.separator + "receiptDataFile" + File.separator;
                filePath = path + File.separator + fileName + ".txt";
                newFileContent = fileName + "|" + fileId;
            } else {
                path = FGBiz.dspCenter.dspSet.dataDirPath + File.separator + "dataFile" + File.separator + bankFront.code + File.separator + "cltRefNoFile" + File.separator;
                filePath = path + File.separator + cltRefNo + ".txt";
                newFileContent = cltRefNo;
            }
            File batFile = new File(filePath);
            if (!batFile.getParentFile().exists()) {
                batFile.getParentFile().mkdirs();
            }
            String fileContent = "";
            if (!batFile.exists()) {
                batFile.createNewFile();
            } else {
                fileContent = FtpUtil.getTextFromFile(filePath, getCharset());
                if (fileContent.contains(newFileContent)) {
                    return;
                }
            }
            fos = new FileOutputStream(batFile);
            fos.write(fileContent.concat(newFileContent).getBytes());
        } catch (Exception e) {
            System.out.println(e.getMessage());
        } finally {
            try {
                if (fos != null) {
                    fos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 根据票据ID调用银行接口查回票据状态
     *
     * @param billNo
     * @return
     */
    public String getBillStateByBillNo(String billNo, String actNum) {
        WriteBankLogLn("查询票据[" + billNo + "]状态...");
        String billState = "";
        try {
            XmlTextWriter xmlWriter = new XmlTextWriter();
            xmlWriter.autoFormat = false;
            writeCommonHeaderEn(xmlWriter, "encoding=\"gb2312\"");
//            < SECURITIES_MSGSRQV1>
            xmlWriter.writeStartElement("SECURITIES_MSGSRQV1");
//            <EBFACEQUERYTRNRQ>
            xmlWriter.writeStartElement("EBFACEQUERYTRNRQ");
//            <TRNUID/>	客户端交易的唯一流水号
            String trnuId = getQryTransID();
            xmlWriter.writeElementString("TRNUID", trnuId);
//            建议值为YYYYMMDD+序号，最长30位	必输
//            <RQBODY>		必输
            xmlWriter.writeStartElement("RQBODY");
//                    <BILLCODE/>	票据号码,30位	必输
            xmlWriter.writeElementString("BILLCODE", billNo);
//            <ACCTID/>	操作员账户代号,最大32位	必输
            xmlWriter.writeElementString("ACCTID", actNum);
//                    </RQBODY>
//            </EBFACEQUERYTRNRQ>
//            </ SECURITIES_MSGSRQV1>
            xmlWriter.writeEndDocument();
            String xmlSend = writeContentLength(xmlWriter);
            String[] result = sendToBank(xmlSend);
            if (result[0].length() == 0) {
                String returnXml = result[1].substring(result[1].indexOf("<FOX>"), result[1].length());
                StringBuilder tmpSbmsg = new StringBuilder();
                XmlTextReader tmpbkReader = loadBankRespXmlReader(returnXml, tmpSbmsg);
                if (tmpbkReader != null) {
                    String resultCode = tmpbkReader.getFirstText("/FOX/SECURITIES_MSGSRSV1/EBFACEQUERYTRNRS/STATUS/CODE");
                    String resultMsg = tmpbkReader.getFirstText("/FOX/SECURITIES_MSGSRSV1/EBFACEQUERYTRNRS/STATUS/MESSAGE");
                    if ("0".equals(resultCode)) {
                        if (tmpbkReader.read("/FOX/SECURITIES_MSGSRSV1/EBFACEQUERYTRNRS/RSBODY")) {
                            //票据状态
                            billState = tmpbkReader.readedXElement.getSingleTextNotNull("BILLSTATUS");
                        } else {
                            throw new Exception("报文中没有票据正面信息的内容");
                        }

                    } else {
                        WriteBankLogLn("查询票号" + billNo + "票据状态失败, 原因:" + resultCode + " - " + resultMsg);
                    }
                } else {
                    WriteBankLogLn("查询票号" + billNo + "票据状态失败, 原因:" + tmpbkReader.toString());
                }
            } else {
                WriteBankLogLn("查询票号" + billNo + "票据状态失败, 原因:" + result[1]);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            WriteBankLogLn("查询票号" + billNo + "票据状态失败, 原因:" + ex.getMessage());
        }
        return billState;
    }
}
